<?php
/**
 * BaseProcess_mysql
 * - The base object for all DAO extension
 * - Assume that using PDOdb for connection
 * - Global connection $dbcon
 * @author Do Truong Giang
 * @copyright Copyright &copy; 2009, Runsystem
 */
include_once("Criteria.class.php");
class BaseProcess {
	protected $tableName;
	protected $attribute;
	public $primaryKeyName;
	
	/**
	 * Constructor
	 */
	public function BaseProcess($tableName) {
		$this->tableName = $tableName;
		$this->attribute = array();
		$this->primaryKeyName = $tableName . "_id";
	}
	/**
	 * setPrimaryKeyName
	 * - Set the value to primaryKey
	 * - Use only for fomatted primary key different "tableName_id"
	 * @since 1.0 - 20-05-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function setPrimaryKeyName($value) {
		$this->primaryKeyName = $value;
	}
	/**
	 * startTransaction
	 * - Begin the transaction
	 * @since 1.0 - 28-04-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function startTransaction(){
	 	global $dbcon;
	 	$dbcon->beginTransaction();
	 }
	 
	 /**
	 * commit
	 * - End the transaction
	 * @since 1.0 - 28-04-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function commit(){
	 	global $dbcon;
	 	$dbcon->commit();
	 }
	 
	 /**
	 * rollBack
	 * - rollBack the transaction
	 * @since 1.0 - 28-04-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function rollBack(){
	 	global $dbcon;
	 	$dbcon->rollBack();
	 }
	 
	 /**
	  * getPrimaryKey
	  * - Get the primary key
	  * @return String : primary key
	  * @author Nguyen Thanh Quyen
	  * @since 1.0 - 25-06-2009
	  */
	 public function getPrimaryKey() {
	 	return $this->primaryKeyName;
	 }
	 
	 
	 /**
	  * setAttributes
	  * - Set one array to attribute
	  * @param Array : arrat of attribute
	  * @author Nguyen Thanh Quyen
	  * @since 1.0 - 19-05-2009 
	  */
	public function setAttributes($arrayAttributes) {
	 	if(is_array($arrayAttributes)) {
	 		foreach($arrayAttributes as $key=>$value) {
	 			$this->setAttribute($key,$value);
	 		}
	 	}
	 } 
	 
	/**
	 * setAttribute
	 * - Set a new attribute for this object
	 * @param String $attName The name of attribute. Should be similar to the field name in database
	 * @param Mixed $attValue The value of attribute. It will be set to database when be saved or updated
	 * @return void
	 */
	public function setAttribute($attName, $attValue) {
		$this->attribute[$attName] = $attValue;
	}
	
	/**
	 * getAttribute
	 * - Get the value of an attribute based on attribute's name
	 * @param String $attName The name of attribute
	 * @return String : the attribute name 
	 * @since 1.0 - Feb 2, 2008
	 */
	public function getAttribute($attName) {
		return $this->attribute[$attName];
	}
	
	/**
	 * getAttributes
	 * @author Nguyen Thanh Quyen
	 * @since 1.0 - 06-07-2009
	 */
	public function getAttributes() {
		return $this->attribute;
	}
	
	/**
	 * execute
	 * - Execute a query
	 * - Do not use PDOdb::Execute function, use BaseObject::execute is better
	 * @param Object $c : object criteria
	 * @param Integer $flag :the type of query
	 * @param Object $fetchMode
	 * @return mixed $result The array contains all of the remaining rows or the number of record delete, modifie
	 * @author Nguyen Thanh Quyen
	 * @since 1.0 - 27-04-2009
	 */
	public function execute($c, $flag , $fetchMode = PDO::FETCH_BOTH) {
		$sql = '';
		//Create connection
		global $dbcon;
		switch ($flag) {
			// SELECT
			case '1':
				$sql = $c->getSelectSql();
				$stmt = $dbcon->query($sql);
				if($stmt){
					$result = $stmt->fetchAll($fetchMode);
				}
				break;
			// INSERT
			case '2':
				$sql = $c->getInsertSql();
				$dbcon->exec($sql);
				$sql1 = "SELECT LAST_INSERT_ID()";
				$stmt = $dbcon->query($sql1);
				$res = $stmt->fetchAll($fetchMode);
				foreach($res as $row) {
					$result = $row[0];
				}
				break;
			// UPDATE
			case '3':
				$sql = $c->getUpdateSql();
				$result = $dbcon->exec($sql);
				break;
			// DELETE
			case '4':
				$sql = $c->getDeleteSql();
				$result = $dbcon->exec($sql);
				break;
		}
		return $result;
	}
	
	/**
	 * select
	 * - Get the array records
	 * @return Array : the array of records
	 * @since 1.0 - 28-04-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function select($c) {
		$flag = '1';	
		// Execute
		$fetchMode = PDO::FETCH_ASSOC;
		$res = $this->execute($c, $flag, $fetchMode);
		return $res;
	}
	
	/**
	 * insertWithoutKey
	 * - Remove the primary key from query
	 */
	public function insertWithoutKey() {
		// Remove the primary key if exists
		$i = 0;
		foreach ($this->attribute as $key => $value) {
			if ($key == $this->primaryKeyName) {
				array_splice($this->attribute, $i, 1);
				break;
			}
			$i++;
		}
		return $this->insert();
	}
	
	/**
	 * insert
	 * - Insert a record to table
	 * - Read the content from $attribute and insert to table $tableName
	 * @return Integer The id of inserted record
	 * @since 1.0 - 27-04-2009
	 */
	public function insert($c = null) {
		$flag = '2';
		if($c === null){	
			$count = count($this->attribute);
			if ($count === 0) {
				return 0;
			}
			else {
				$attributeNames = array_keys($this->attribute);
				$attributeValues = array_values($this->attribute);
				for ($i = 0; $i < $count; $i++) {
					if ($attributeValues[$i] === null) {
						$attributeValues[$i] = "NULL";
					}
				}
				// Prepare criteria before execute
				$c = Criteria::factoryCriteria();
				$c->setTableNames($this->tableName);
				$c->setColumns($attributeNames);
				$c->setValues($attributeValues);
			}
		}
		// Execute
		$id = $this->execute($c, $flag);
		$this->setAttribute($this->primaryKeyName, $id);
		return $id;
	}
	
	/**
	 * update
	 * - Update a record in a table based on it's primary key
	 * - Read the content from $attribute and update the table $tableName
	 * @return Integer :number of updated records
	 * @since 1.0 - 27-04-2009
	 */
	public function update($c = null) {
		$flag = '3';
		if($c === null){
			$count = count($this->attribute);
			if ($count === 0) {
				return 0;
			}else {
				$attributeNames = array_keys($this->attribute);
				$attributeValues = array_values($this->attribute);
				for ($i = 0; $i < $count; $i++) {
					if ($attributeValues[$i] === null) {
						$attributeValues[$i] = "NULL";
					}
				}
				// Prepare criteria before execute
				$c = Criteria::factoryCriteria();
				$c->setTableNames($this->tableName);
				$c->setCondition($this->primaryKeyName, $this->getAttribute($this->primaryKeyName), "=");
				$i = 0;
				foreach ($this->attribute as $key => $value) {
					if ($key == $this->primaryKeyName) {
						array_splice($this->attribute, $i, 1);
						break;
					}
					$i++;
				}
				$c->setColumns(array_keys($this->attribute));
				$c->setValues(array_values($this->attribute));
			}
		}
		// Execute
		$num = $this->execute($c, $flag);
		return $num;
	}
	
	/**
	 * delete
	 * - Delete this object
	 * @return Integer : number of deleted records
	 * @since 1.0 - 27-04-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function delete($c = null) {
		$flag = '4';
		if($c === null){
			$count = count($this->attribute);
			if ($count === 0) {
				return 0;
			}
			else {
				$attributeNames = array_keys($this->attribute);
				$attributeValues = array_values($this->attribute);
				for ($i = 0; $i < $count; $i++) {
					if ($attributeValues[$i] === null) {
						$attributeValues[$i] = "NULL";
					}
				}
				// Prepare criteria before execute
				$c = Criteria::factoryCriteria();
				$c->setTableNames($this->tableName);
				$c->setColumns($attributeNames);
				$c->setValues($attributeValues);
				// Create condition
				for($i = 0; $i < $count; $i++ ){
					$c->addOr($attributeNames[$i],$attributeValues[$i], "=");
				}
			}
		}
		// Execute
		$num = $this->execute($c, $flag);
		return $num;
	}
	
	/**
	 * getTableName
	 * - Get the name of table
	 * @return String
	 * @since 1.0 - 28-04-2009
	 * @author Nguyen Thanh Quyen
	 */
	public function getTableName() {
		return $this->tableName;
	}
	
	/**
	 * getByPrimaryKey
	 * - Assume that the primary key was set
	 * - Get first record's information based on it's primary key
	 * @param String $key : the key id
	 * @return Array : the array of records
	 * @since 1.0 - Feb 2, 2008
	 * @version 1.1
	 */
	public function getByPrimaryKey($key) {
		$primaryKey = $this->getPrimaryKey();
		// Prepare criteria
		$c = Criteria::factoryCriteria();
		$c->setTableNames($this->tableName);
		$c->setCondition("$primaryKey", "$key", "=");
		// Execute
		$res = $this->select($c);
		return $res;
	}
	
	/**
	 * deleteByPrimaryKey
	 * - delete record by primary key
	 * @author Nguyen Thanh Quyen
	 * @since 1.0 - 26-06-2009
	 */
	public function deleteByPrimaryKey($key) {
		$primaryKey = $this->getPrimaryKey();
		// Prepare criteria
		$c = Criteria::factoryCriteria();
		$c->setTableNames($this->tableName);
		$c->setCondition("$primaryKey", "$key", "=");
		// Execute
		$res = $this->delete($c);
		return $res;
	}
	
	/**
	 * getByAttribute
	 * - Set this object by getting by some predefined attributes
	 * - Can used for case Key
	 * @param Array $attr : array with key and value 
	 * @return Boolean
	 * @since 1.0 - Feb 2, 2008
	 * @version 1.1
	 */
	public function getByAttribute($attr) {
		$flag = 1;
		$attrKey = array_keys($attr);
		$attrValue = array_values($attr);
		$count = count($attr);
		
		// Prepare criteria
		$c = Criteria::factoryCriteria();
		$c->setTableNames($this->tableName);
		for($i = 0 ; $i < $count; $i++){
			$c->addAnd($attrKey[$i], $attrValue[$i], "=");
		}
		// Execute
		$fetchMode = PDO::FETCH_ASSOC;
		$res = $this->execute($c, $flag, $fetchMode);
		return $res;
	}
	
	/**
	 * deleteByAttribute
	 * - Delete all record has that attribute
	 * @author Nguyen Thanh Quyen
	 * @since 1.0 - 01-07-2009
	 * @return Boolean : true if successed, false if failed
	 */
	public function deleteByAttribute($attr) {
		$attrKey = array_keys($attr);
		$attrValue = array_values($attr);
		$count = count($attr);
		
		// Prepare criteria
		$c = Criteria::factoryCriteria();
		$c->setTableNames($this->tableName);
		for($i = 0 ; $i < $count; $i++){
			$c->addAnd($attrKey[$i], $attrValue[$i], "=");
		}
		// Execute
		$res = $this->delete($c);
		if($res!=0) {
			return true;
		}
		else {
			return false;
		}
	}	
	/**
	 * selectOne
	 * - Only select first record satisfies the condition specified in $c
	 * @param Criteria $c The condition object
	 * @return Boolean
	 * @since 1.0 - Feb 2, 2008
	 * @version 1.1
	 */
	public function selectOne($c) {
		$flag = 1;
		$result = false;
		// Execute
		$fetchMode = PDO::FETCH_ASSOC;
		$res = $this->execute($c, $flag, $fetchMode);
		// Set the attribute
		foreach($res as $row){
			$result = true;
			foreach ($row as $name=>$value) {
				$this->setAttribute($name, $value);
			}
			break;
		}
		return $result;
	}
}
?>